//
//  DepartmentViewFlowLayout.swift
//  EyeVisionForPatients
//
//  Created by PMC on 2020/2/9.
//  Copyright © 2020 tao Tao. All rights reserved.
//

import UIKit

enum ItemsHorizontalAlignment: Int {
    case flow
    case left
    case center
    case right
}

enum ItemsVerticalAlignment {
    case center
    case top
    case bottom
}

enum ItemsDirection {
    case leftToRight
    case rightToLeft
}

@objc protocol DepartmentViewFlowLayoutDelegate: NSObjectProtocol {
    func waterFlowLayout(layout: DepartmentViewFlowLayout, indexPath: IndexPath, itemWidth: CGFloat) -> CGFloat
    @objc optional func columnCountInWaterFlowLayout(layout: DepartmentViewFlowLayout) -> Int
    
    @objc optional func columnMarginInWaterFlowLayout(layout: DepartmentViewFlowLayout) -> CGFloat
    @objc optional func rowMarginInWaterFlowLayout(layout: DepartmentViewFlowLayout) -> CGFloat
    @objc optional func edgeInsetsInWaterFlowLayout(layout: DepartmentViewFlowLayout) -> UIEdgeInsets
}

class DepartmentViewFlowLayout: UICollectionViewLayout {
    weak var delegate: DepartmentViewFlowLayoutDelegate?
    
    private let defaultColumnCount: Int = 3
    private let defaultColumnMargin: CGFloat = 10
    private let defaultRowMargin: CGFloat = 10
    private let defaultEdgeInsets: UIEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
    
    private lazy var attributes = [UICollectionViewLayoutAttributes]()
    private lazy var columnHeights = [CGFloat]()
    private var contentHeight: CGFloat = 0
    
    override func prepare() {
        super.prepare()
        
        if collectionView == nil { return }
        
        columnHeights.removeAll()
        
        for _ in 0..<columnCount() {
            columnHeights.append(edgeInsets().top)
        }
        
        attributes.removeAll()
        
        let count = (collectionView?.numberOfItems(inSection: 0))!
        let width = (collectionView?.frame.size.width)!
        let colMagin = (CGFloat)(columnCount() - 1) * columnMargin()
        let cellWidth = (width - edgeInsets().left - edgeInsets().right - colMagin) / CGFloat(columnCount())
        
        for i in 0..<count {
            let indexPath = IndexPath(item: i, section: 0)
            let attr = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            let cellHeight = (delegate?.waterFlowLayout(layout: self, indexPath: indexPath, itemWidth: cellWidth))!
            
            var minColumnHeight = columnHeights[0]
            var minColumn = 0
            for i in 1..<columnCount() {
                let colHeight = columnHeights[i]
                
                if colHeight < minColumnHeight {
                    minColumnHeight = colHeight
                    minColumn = i
                }
            }
            
            let cellX = edgeInsets().left + CGFloat(minColumn) * (columnMargin() + cellWidth)
            var cellY = minColumnHeight
            if cellY != edgeInsets().top {
                cellY = rowMargin() + cellY
            }

            attr.frame = CGRect(x: cellX, y: cellY, width: cellWidth, height: cellHeight)
            let maxY = cellY + cellHeight;

            
            columnHeights[minColumn] = maxY
            let maxContentHeight = columnHeights[minColumn]
            if CGFloat(contentHeight) < CGFloat(maxContentHeight) {
                contentHeight = maxContentHeight
            }
            attributes.append(attr)
        }
    }
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return self.attributes
    }
    
    override var collectionViewContentSize: CGSize{
        get {
            return CGSize(width: 0, height: CGFloat(contentHeight) + CGFloat(edgeInsets().bottom))
        }
        set {
            self.collectionViewContentSize = newValue
        }
    }
}

private extension DepartmentViewFlowLayout {
    func columnCount() -> Int {
        if delegate != nil && (delegate?.responds(to: #selector(delegate?.columnCountInWaterFlowLayout(layout:))))! {
            return (delegate?.columnCountInWaterFlowLayout!(layout: self))!
        } else {
            return defaultColumnCount
        }
    }
    
    func columnMargin() -> CGFloat {
        if delegate != nil && (delegate?.responds(to: #selector(delegate?.columnMarginInWaterFlowLayout(layout:))))! {
            return (delegate?.columnMarginInWaterFlowLayout!(layout: self))!
        } else {
            return defaultColumnMargin
        }
    }
    
    func rowMargin() -> CGFloat {
        if delegate != nil && (delegate?.responds(to: #selector(delegate?.rowMarginInWaterFlowLayout(layout:))))! {
            return (delegate?.columnMarginInWaterFlowLayout!(layout: self))!
        } else {
            return defaultRowMargin
        }
    }
    
    func edgeInsets() -> UIEdgeInsets {
        if delegate != nil && (delegate?.responds(to: #selector(self.delegate?.edgeInsetsInWaterFlowLayout(layout:))))!{
            return (delegate?.edgeInsetsInWaterFlowLayout!(layout: self))!
        }else{
            return defaultEdgeInsets
        }
    }
}
